import React, {useState, useReducer} from "react";
import {Button, Card} from 'antd';

let render_count = 0

function Problem_1() {
    render_count = render_count + 1

    const [count, setCount] = useState(1)

    /**
     *   下面代码想要在加载完组件后的  1s 后 让count加1
     *   效果:代码死循环了
     *   原因:在调用  通过 useState 方法创建的 setCount 修改数据后 组件会重新执行  于是定时器也会被一直重复调用
     */
    //  todo 测试时 释放代码
    // alert('组件重新调用了')
    // setTimeout(()=>{
    //     setCount(count + 1)
    // },1000)

    return (
        <div className={'module'}>
            <div className={'flex-items-center'}>
                <h3>细节1:</h3>
                <span>使用 useState 方法 修改组件值后 组件会 <span className={'label-red'}>整个</span> 重新执行</span>
            </div>
            <h4>
                组件被调用的次数:{render_count}
                <br/>
                当前count值为:{count}
            </h4>
            <Button onClick={() => setCount(pre => pre + 1)}>点击+1</Button>
        </div>
    )
}

function Problem_2() {
    const [count, setCount] = useState(0)
    const handelClickError = () => {
        setCount(count + 1)
        setCount(count + 1) // 0 + 1
        setCount(count + 1) // 0 + 1
        setCount(count + 1) // 0 + 1
        setCount(count + 1) // 0 + 1
        /**
         * 问题:
         *  1. 打印出的结果为 改变前的值 而不是改变后的值; 证明了 setCount 方法是个异步操作
         *  2. 连续使用 setCount  代码都执行了 但是值只会加1; 原因是 setCount 方法是个异步操作   连续调用都是拿的原来的值去加1
         * **/
        console.log('点击后的count 值为:', count)
    }
    const handelClickSuccess = () => {
        /**
         * 解决办法:
         *   问题1: 使用 setCount 回调函数的方式  在回调里去打印 最近的值   setCount(count=> {
         *             console.log('点击后的count 值为:', count)
         *             return count
         *         })
         *   问题2:  使用setCount 回调函数的方式  setCount(count=> count+1)
         * */
        setCount(count => count + 1)
        setCount(count => count + 1)
        setCount(count => count + 1)
        setCount(count => count + 1)
        setCount(count => count + 1)

        setCount(count => {
            console.log('点击后的count 值为:', count)
            return count
        })
    }
    return (
        <div className={'module'}>
            <div className={'flex-items-center'}>
                <h3>细节2:</h3>
                <div>
                    <span>使用 useState 方法修改值 是一个 </span>
                    <span className={'label-red'}>异步操作</span>
                </div>
            </div>
            <h4>当前count值为:{count}</h4>
            <Button onClick={() => handelClickError()}> 问题演示: 点击连续加5 </Button>
            <Button onClick={() => handelClickSuccess()}> 解决方法演示: 点击连续加5</Button>
        </div>
    )
}


function Problem_3() {
    const [count, setCount] = useState(1)
    let x = 100
    const handelClick = () => {
        setCount((count) => {
            x = x + 1
            return count + 1
        })
    }
    return (
        <div className={'module'}>
            <div className={'flex-items-center'}>
                <h3>细节3:</h3>
                <div>使用 useState 方法 定义的值 会被 <span className={'label-red'}>缓存</span>;</div>
            </div>
            <div className={'definition-2'}>点击后 未使用 useState定义的 x 的值 未发生改变<br/>
                原因:因为使用useState方法去修改count值 会导致组件重新执行,定义在组件中的 X 值被重置;<br/>
                而使用useState定义的 count 未被重置 说明 react将 count缓存了 每次组件重新执行 都能拿到上次最近的值
            </div>
            <h4>使用 useState 定义的 当前count值为 当前值为:{count}</h4>
            <h4>未使用 useState 定义的 当前X值为 当前值为:{x}</h4>
            <Button onClick={() => handelClick()}>点击让x和count都+1</Button>
        </div>
    )
}

export default () => {
    return (
        <Card hoverable>
            <div style={{marginBottom:10}}>
                <h1>useState的4个细节</h1>
                <h4>1.组件会重新执行,避免死循环</h4>
                <h4>2.异步执行--问题与解决</h4>
                <h4>3.缓存效果</h4>
                <h4>4.需要在组件内使用 </h4>
            </div>
            <div className={'flex-y-gap'}>
                <Problem_1/>
                <Problem_2/>
                <Problem_3/>
            </div>
        </Card>
    )
}